package mal.carbonization;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

import java.util.List;
import java.util.Random;

import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;

public class BlockFurnaces extends BlockContainer
{
    /**
     * Is the random generator used by furnace to drop the inventory contents in random directions.
     */
    private Random furnaceRand = new Random();

    /** True if this is an active furnace, false if idle */
    private final boolean isActive;

    /**
     * This flag is used to prevent the furnace inventory to be dropped upon block removal, is used internally when the
     * furnace block changes from idle to active and vice-versa.
     */
    private static boolean keepFurnaceInventory = false;

    protected BlockFurnaces(int par1, boolean par2)
    {
        super(par1, Material.rock);
        this.isActive = par2;
        this.setRequiresSelfNotify();
        this.blockIndexInTexture = 24;
        this.setTextureFile("/mal/carbonization/carbonizationTexture.png");
        this.setCreativeTab(CreativeTabs.tabDecorations);
    }
    
    public boolean hasTileEntity(int metadata)
    {
    	return true;
    }

    /**
     * Returns the ID of the items to drop on destruction.
     */
    public int idDropped(int par1, Random par2Random, int par3)
    {
        return carbonization.furnaceBlock.blockID;
    }
    
    /***
     * Transform a standard metadata into an int array of side and furnace values
     * First index is the furnace, second is the side
     */
    private int[] transformMetadata(int metadata)
    {
    	int[] data = new int[2];
    	
    	//metadata contains the side and meta values
    	//0-3, 4-7, 8-11
    	//the side values exclude the top and bottom (0, 1)
    	//so we adjust appropriately for the shift down 2 indices
    	
    	if (metadata >=0 && metadata < 4)
    	{
    		data[1] = metadata+2;
    		data[0] = 0;
    	}
    	else if (metadata >= 4 && metadata < 8)
    	{
    		data[1] = metadata-2;
    		data[0] = 4;
    	}
    	else
    	{
    		data[1] = metadata-6;
    		data[0] = 8;
    	}
    	
    	return data;
    }
    
    /***
     * Transform our shifted metadata value array into a standard nibble
     */
    private int transformSideandMeta(int furnace, int side)
    {
    	int metadata;
    	
    	side = side-2;
    	metadata = furnace+side;
    	
    	return metadata;
    }

    /**
     * Called whenever the block is added into the world. Args: world, x, y, z
     */
    public void onBlockAdded(World par1World, int par2, int par3, int par4)
    {
    	int metadata = par1World.getBlockMetadata(par2, par3, par4);
            par1World.setBlockTileEntity(par2, par3, par4, this.createNewTileEntity(par1World, transformMetadata(metadata)[0]));
    }

    /**
     * Update which block ID the furnace is using depending on whether or not it is burning
     */
    public static void updateFurnaceBlockState(boolean par0, World par1World, int par2, int par3, int par4)
    {
        int var5 = par1World.getBlockMetadata(par2, par3, par4);
        TileEntity var6 = par1World.getBlockTileEntity(par2, par3, par4);
        keepFurnaceInventory = true;

        if (par0)
        {
            par1World.setBlockWithNotify(par2, par3, par4, carbonization.furnaceBlockActive.blockID);
        }
        else
        {
            par1World.setBlockWithNotify(par2, par3, par4, carbonization.furnaceBlock.blockID);
        }

        keepFurnaceInventory = false;
        par1World.setBlockMetadataWithNotify(par2, par3, par4, var5);

        if (var6 != null)
        {
            var6.validate();
            par1World.setBlockTileEntity(par2, par3, par4, var6);
        }
    }

    @SideOnly(Side.CLIENT)

    /**
     * Retrieves the block texture to use based on the display side. Args: iBlockAccess, x, y, z, side
     */
    public int getBlockTexture(IBlockAccess par1IBlockAccess, int x, int y, int z, int side)
    {
    	//get the correct metadata and split it into side and metadata values
    	int metadata = par1IBlockAccess.getBlockMetadata(x, y, z);
    	//metadata contains the side and meta values
    	//0-4, 4-7, 8-11
    	
    	int[] value = transformMetadata(metadata);
    	
    	//if the side the face is is the same as the side we are looking at, show the face
    	if(side==value[1])
    	{
    		//if we are active use the burning texture instead
    		if(isActive)
    		{
    			switch(value[0])
	        	{
	        	case 0:
	            	return this.blockIndexInTexture+17;
	        	case 4:
	            	return this.blockIndexInTexture + 19;
	        	case 8:
	            	return this.blockIndexInTexture + 21;
	        	default:
	            	return 0;
	        	}	
    		}
    		else
    		{
	    		switch(value[0])
	        	{
	        	case 0:
	            	return this.blockIndexInTexture;
	        	case 4:
	            	return this.blockIndexInTexture + 2;
	        	case 8:
	            	return this.blockIndexInTexture + 4;
	        	default:
	            	return 0;
	        	}
    		}
    	}
    	else if (side ==0 || side ==1)
    	{
    		switch(value[0])
    		{
    		case 0:
    			return this.blockIndexInTexture+16;
    		case 4:
    			return this.blockIndexInTexture+18;
    		case 8:
    			return this.blockIndexInTexture+20;
    		default:
    			return 0;
    		}
    	}
    	else
    	{
    		switch(value[0])
    		{
    		case 0:
    			return this.blockIndexInTexture+1;
    		case 4:
    			return this.blockIndexInTexture+3;
    		case 8:
    			return this.blockIndexInTexture+5;
    		default:
    			return 0;
    		}
    		//return par5 < 4 ? this.blockIndexInTexture+2*metadata/10 : (this.isActive ? this.blockIndexInTexture + 16 : this.blockIndexInTexture - 1);
    	}
    }
    
    /**
     * Determines the damage on the item the block drops. Used in cloth and wood.
     */
    public int damageDropped(int par1)
    {
    	//metadata contains the side and meta values
    	//0-3, 4-7, 8-11
    	
    	int[] value = transformMetadata(par1);
    	return (value[0]);
    }
    
    @SideOnly(Side.CLIENT)
    public void getSubBlocks(int par1, CreativeTabs par2CreativeTabs, List par3List)
    {
    	//don't do this for the active furnace
    	if(!isActive)
    	{
	    	par3List.add(new ItemStack(par1, 1, 0));
	    	par3List.add(new ItemStack(par1, 1, 4));
	    	par3List.add(new ItemStack(par1, 1, 8));
	    	//par3List.add(new ItemStack(par1, 1, 3));
    	}
    }


    @SideOnly(Side.CLIENT)

    /**
     * A randomly called display update to be able to add particles or other items for display
     */
    public void randomDisplayTick(World par1World, int x, int y, int z, Random par5Random)
    {
        if (isActive)
        {
            int metadata = par1World.getBlockMetadata(x, y, z);

        	
        	int[] value = transformMetadata(metadata);
            
            float var7 = (float)x + 0.5F;
            float var8 = (float)y + 0.0F + par5Random.nextFloat() * 6.0F / 16.0F;
            float var9 = (float)z + 0.5F;
            float var10 = 0.52F;
            float var11 = par5Random.nextFloat() * 0.6F - 0.3F;

            if (value[1] == 4)
            {
                par1World.spawnParticle("smoke", (double)(var7 - var10), (double)var8, (double)(var9 + var11), 0.0D, 0.0D, 0.0D);
                par1World.spawnParticle("flame", (double)(var7 - var10), (double)var8, (double)(var9 + var11), 0.0D, 0.0D, 0.0D);
            }
            else if (value[1] == 5)
            {
                par1World.spawnParticle("smoke", (double)(var7 + var10), (double)var8, (double)(var9 + var11), 0.0D, 0.0D, 0.0D);
                par1World.spawnParticle("flame", (double)(var7 + var10), (double)var8, (double)(var9 + var11), 0.0D, 0.0D, 0.0D);
            }
            else if (value[1] == 2)
            {
                par1World.spawnParticle("smoke", (double)(var7 + var11), (double)var8, (double)(var9 - var10), 0.0D, 0.0D, 0.0D);
                par1World.spawnParticle("flame", (double)(var7 + var11), (double)var8, (double)(var9 - var10), 0.0D, 0.0D, 0.0D);
            }
            else if (value[1] == 3)
            {
                par1World.spawnParticle("smoke", (double)(var7 + var11), (double)var8, (double)(var9 + var10), 0.0D, 0.0D, 0.0D);
                par1World.spawnParticle("flame", (double)(var7 + var11), (double)var8, (double)(var9 + var10), 0.0D, 0.0D, 0.0D);
            }
        }
    }

    public int getBlockTextureFromSide(int side)
    {
    	switch(side)
    	{
    	case 0:
    		return this.blockIndexInTexture+16;
    	case 1:
    		return this.blockIndexInTexture+16;
    	case 4:
    		return this.blockIndexInTexture;
    	default:
    		return this.blockIndexInTexture+1;
    	}
    }
    
    /**
     * Returns the block texture based on the side being looked at.  Args: side, metadata
     */
    @Override
    public int getBlockTextureFromSideAndMetadata(int side, int metadata)
    {
    	//get the correct metadata and split it into side and metadata values
    	
    	int[] value = transformMetadata(metadata);
    	
    	//if the side the face is is the same as the side we are looking at, show the face
    	if(side==4)
    	{
	    		switch(value[0])
	        	{
	        	case 0:
	            	return this.blockIndexInTexture;
	        	case 4:
	            	return this.blockIndexInTexture + 2;
	        	case 8:
	            	return this.blockIndexInTexture + 4;
	        	default:
	            	return 0;
	        	}
    	}
    	else if (side ==0 || side ==1)
    	{
    		switch(value[0])
    		{
    		case 0:
    			return this.blockIndexInTexture+16;
    		case 4:
    			return this.blockIndexInTexture+18;
    		case 8:
    			return this.blockIndexInTexture+20;
    		default:
    			return 0;
    		}
    	}
    	else
    	{
    		switch(value[0])
    		{
    		case 0:
    			return this.blockIndexInTexture+1;
    		case 4:
    			return this.blockIndexInTexture+3;
    		case 8:
    			return this.blockIndexInTexture+5;
    		default:
    			return 0;
    		}
    		//return par5 < 4 ? this.blockIndexInTexture+2*metadata/10 : (this.isActive ? this.blockIndexInTexture + 16 : this.blockIndexInTexture - 1);
    	}
    }

    /**
     * Called upon block activation (right click on the block.)
     */
    public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
    {
        if (world.isRemote)
        {
            return true;
        }
        else
        {
            TileEntityFurnaces var10 = (TileEntityFurnaces)world.getBlockTileEntity(x, y, z);

            if (var10 == null || par5EntityPlayer.isSneaking())
            {
            	return false;
            }
            par5EntityPlayer.openGui(carbonization.instance, 0, world, x, y, z);

            return true;
        }
    }

    /**
     * Returns a new instance of a block's tile entity class. Called on placing the block.
     */
    public TileEntity createNewTileEntity(World par1World, int metadata)
    {
    	try
    	{
    		return new TileEntityFurnaces(transformMetadata(metadata)[0]);
    	}
    	catch(Exception e)
    	{
    		System.out.println("Oh dear, something broke with the tile entities, prod Mal so he can fix it.");
    	}
		return null;
    }

    /**
     * Called when the block is placed in the world.
     */
    public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving)
    {
        int var6 = MathHelper.floor_double((double)(par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;

        if (var6 == 0)
        {
            par1World.setBlockMetadataWithNotify(par2, par3, par4, 2);
        }

        if (var6 == 1)
        {
            par1World.setBlockMetadataWithNotify(par2, par3, par4, 5);
        }

        if (var6 == 2)
        {
            par1World.setBlockMetadataWithNotify(par2, par3, par4, 3);
        }

        if (var6 == 3)
        {
            par1World.setBlockMetadataWithNotify(par2, par3, par4, 4);
        }
    }
    
    /*
     * Called after the block is placed
     * Convert the current metadata into the correct value
     */
    public void onPostBlockPlaced(World world, int x, int y, int z, int metadata)
    {
    	int partialmetadata = world.getBlockMetadata(x, y, z);
    	world.setBlockMetadataWithNotify(x, y, z, transformSideandMeta(partialmetadata,metadata));
    }

    /**
     * ejects contained items into the world, and notifies neighbours of an update, as appropriate
     */
    public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
    {
        if (!keepFurnaceInventory)
        {
            TileEntityFurnaces var7 = (TileEntityFurnaces)par1World.getBlockTileEntity(par2, par3, par4);

            if (var7 != null)
            {
                for (int var8 = 0; var8 < var7.getSizeInventory(); ++var8)
                {
                    ItemStack var9 = var7.getStackInSlot(var8);

                    if (var9 != null)
                    {
                        float var10 = this.furnaceRand.nextFloat() * 0.8F + 0.1F;
                        float var11 = this.furnaceRand.nextFloat() * 0.8F + 0.1F;
                        float var12 = this.furnaceRand.nextFloat() * 0.8F + 0.1F;

                        while (var9.stackSize > 0)
                        {
                            int var13 = this.furnaceRand.nextInt(21) + 10;

                            if (var13 > var9.stackSize)
                            {
                                var13 = var9.stackSize;
                            }

                            var9.stackSize -= var13;
                            EntityItem var14 = new EntityItem(par1World, (double)((float)par2 + var10), (double)((float)par3 + var11), (double)((float)par4 + var12), new ItemStack(var9.itemID, var13, var9.getItemDamage()));

                            if (var9.hasTagCompound())
                            {
                                var14.func_92014_d().setTagCompound((NBTTagCompound)var9.getTagCompound().copy());
                            }

                            float var15 = 0.05F;
                            var14.motionX = (double)((float)this.furnaceRand.nextGaussian() * var15);
                            var14.motionY = (double)((float)this.furnaceRand.nextGaussian() * var15 + 0.2F);
                            var14.motionZ = (double)((float)this.furnaceRand.nextGaussian() * var15);
                            par1World.spawnEntityInWorld(var14);
                        }
                    }
                }
            }
        }

        super.breakBlock(par1World, par2, par3, par4, par5, par6);
    }

	@Override
	public TileEntity createNewTileEntity(World var1) {
		// TODO Auto-generated method stub
		return null;
	}
}